package com.woniu.controller;

import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.date.DateTime;
import cn.hutool.crypto.digest.DigestUtil;
import com.github.pagehelper.Page;
import com.woniu.config.ContainerCache;
import com.woniu.entity.CtfContainer;
import com.woniu.entity.CtfRange;
import com.woniu.entity.PageBean;
import com.woniu.entity.vo.ContainerVo;
import com.woniu.mapper.CtfContainerMapper;
import com.woniu.service.CtfContainerService;
import com.woniu.util.ResponseData;
import com.woniu.utils.DockerUtils;
import com.woniu.utils.ResponseMyEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * @author nanqiao
 * @description CtfContainer 控制器，提供 容器操作 API
 * @createDate 2025-06-09 17:11:49
 * @Entity com.woniu.entity.CtfContainer
 * (CtfContainer)表控制层
 *
 * @author makejava
 * @since 2025-06-10 12:01:14
 */
@RestController
@RequestMapping("/ctfContainer")
public class CtfContainerController {
    @Autowired
    private CtfContainerService ctfContainerService;
    @Autowired
    private DockerUtils dockerUtils;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private CtfContainerMapper ctfContainerMapper;
    @Autowired
    private ContainerCache containerCache;

    /**
     * @author hq
     * @Description 后续老马说的指定两个路径存放，后面我写
     * @return ResponseMyEntity我封装的结果集，后续统一
     * @throws IOException
     */
        @PostMapping("/createContainer")
        public ResponseMyEntity createContainer(@RequestBody CtfRange range) throws IOException {
            String flag = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
            String containerName = range.getRangeId() + flag.codePointCount(0,4);
            int port = 88;
            ctfContainerService.createContainer(range.getRangeId(),containerName,port,flag);
            return ResponseMyEntity.SUCCESS;
        }

    /**
     * @author hq
     * 启动容器
     * @param containerId 可以是容器名，也可以是id
     * @return
     */
//    @PostMapping("/startContainer")
        public ResponseMyEntity startContainer(String containerId) {
            ctfContainerService.startContainer(containerId);
            return ResponseMyEntity.SUCCESS;
        }
        //停止容器
        @GetMapping("/stopContainer")
        public ResponseMyEntity stopContainer(@RequestParam("containerIdOrName") String containerIdOrName) {
            ctfContainerService.stopContainer(containerIdOrName);
            return ResponseMyEntity.SUCCESS;
        }

    /**删除
     * @author hq
     * @param containerIdOrName 可以是容器名字可以是id
     * @Description 强制删除dokcer的容器
     * @return
     */
    @DeleteMapping("/deleteContainer/{containerIdOrName}")
    public ResponseData<String> deleteContainer(@PathVariable String containerIdOrName) {
//        dockerUtils.removeContainer(containerIdOrName);
        ctfContainerService.removeById(containerIdOrName);
        return ResponseData.ok("删除成功");
    }
    /**
     * 创建并启动容器
     * @author hq
     * @param imageId 镜像id
     * @param containerName 容器名字
     * @param containerPort 容器端口
     * @param flagValue 容器flag
     * @return
     */
    @PostMapping("/createStartContainer")
    public ResponseMyEntity createStartContainer(@RequestParam("imageId") String imageId,
                                                 @RequestParam("containerName") String containerName,
                                                 @RequestParam("containerPort") int containerPort,
                                                 @RequestParam("flagValue") String flagValue) {
        ctfContainerService.createStartContainer(imageId, containerName, containerPort, flagValue);
        return ResponseMyEntity.SUCCESS;
    }
    //用这个不要用上面那个，随机生成flag，将flag保存在redis中，并设置过期时间，放入docker中，端口号从数据库镜像表里面查询
    @PostMapping("/startContainer")
    public SaResult startContainer(@RequestBody CtfRange range) {
        System.out.println(range.getRangeId());
        System.out.println(range.getRangeName());
        ContainerVo response = ctfContainerService.startContainerByIdOrName(range.getRangeId(), range.getRangeName());
        return SaResult.ok().setData(response);
    }
    /**
     * @author hq
     * @param container 修改容器部分信息，后续可能会修改flag存储位置
     * @return
     */
    @PutMapping
    public ResponseData<String> update(@RequestBody CtfContainer container) {
        // 设置更新时间
        container.setUpdateTime(DateTime.now());
        ctfContainerService.updateById(container);
        return ResponseData.ok("更新成功");
    }

    /**
     *
     * @param container 根据id修改容器信息
     * @return
     */
    //根据id修改容器信息
    @PutMapping("/{id}")
    public ResponseData<String> updateById(@RequestBody CtfContainer container) {
        container.setUpdateTime(DateTime.now());
        ctfContainerService.updateById(container);
        return ResponseData.ok("更新成功");
    }

    /**
     * @Description  查询所有容器信息
     * @return
     */
    @GetMapping
    public ResponseData<List<CtfContainer>> list() {
        List<CtfContainer> list = ctfContainerService.list();
        return ResponseData.ok(list);
    }
    /**
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public ResponseData<CtfContainer> getById(@PathVariable Integer id) {
        CtfContainer container = ctfContainerService.getById(id);
        return ResponseData.ok(container);
    }
    /**
     *
     * @param id
     * @param inputFlag
     * @return
     */
    @GetMapping("/verify/{id}/{inputFlag}")
    public ResponseData<?> verifyFlag(@PathVariable Integer id, @PathVariable String inputFlag) {
        // 从 Redis 获取已存储的 flag（可能已过期）
        String storedFlag = (String) redisTemplate.opsForValue().get("flag:" + id);

        if (storedFlag == null) {
            // flag 不存在（已过期）
            return ResponseData.fail(501, "时间到");
        }
        // 对用户输入的 flag 进行 MD5 加密
        String inputMd5 = DigestUtil.md5Hex(inputFlag);
        // 判断是否匹配
        if (inputMd5.equals(storedFlag)) {
            // flag 匹配，获取剩余时间
            Long remainingTtl = redisTemplate.getExpire("flag:" + id);
            if (remainingTtl == null || remainingTtl <= 0) {
                return ResponseData.fail(501, "时间到");
            }
            // 转换为“X分钟Y秒”
            long minutes = remainingTtl / 60;
            long seconds = remainingTtl % 60;
            String displayTime;
            if (minutes > 0 && seconds > 0) {
                displayTime = minutes + "分钟" + seconds + "秒";
            } else if (minutes > 0) {
                displayTime = minutes + "分钟";
            } else {
                displayTime = seconds + "秒";
            }
            FlagVerifyResponse response = new FlagVerifyResponse()
                    .setResult("flag 正确")
                    .setRemainingTimeDesc(displayTime);
            return ResponseData.ok(response);
        } else {
            return ResponseData.fail(500, "flag 错误");
        }

    }
    @GetMapping("/checkFlag")
    public SaResult verifyFlag(@RequestParam("containerId") String containerId, @RequestParam("inputFlag") String inputFlag) {
        // 从 Redis 获取加密后的正确 flag
        String correctFlag = (String) redisTemplate.opsForValue().get("flag:" + containerId);
        // 对用户输入进行 MD5 加密
//        String md5Input = DigestUtil.md5Hex(userInputFlag);
        if (inputFlag.equals(correctFlag)) {
            // 验证通过
            // 1. 删除 Redis 中的 flag
            redisTemplate.delete("flag:" + containerId);
            // 2. 停止并删除容器
        /*    dockerUtils.stopAndRemoveContainer(containerId);
            containerCache.removeContainer(containerId);*/
            // 3. 更新数据库：设置 is_flag_match = 1，并更新 update_time
            ctfContainerService.updateFlagMatchAndTime(containerId);
            return SaResult.ok("验证成功，容器已销毁");
        } else {
            return SaResult.error("验证失败，flag 不匹配");
        }
    }

    /**
     * @author Hubbrta
     * @Description 分页条件查询容器信息
     */
    @GetMapping("/selectPage")
    public SaResult selectPage(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            CtfContainer container
    ){
        PageBean<CtfContainer> pageInfo =ctfContainerService.selectPage(pageNum,pageSize,container);
        return SaResult.ok().setData(pageInfo);
    }

    /**
     * 销毁容器
     * @param containerId
     * @return
     */
    @DeleteMapping("/destroyContainer")
    public SaResult destroyContainer(@RequestParam String containerId) {
        System.out.println("销毁容器: " + containerId);

        // 1. 删除 Docker 容器
        dockerUtils.stopAndRemoveContainer(containerId);

        // 2. 更新数据库中的 updateTime 字段
        ctfContainerService.updateContainerUpdateTime(containerId, new Date());

        // 3. 可选：从缓存中移除容器（如果后续不再使用）
         containerCache.removeContainer(containerId);

        // 4. 不删除 Redis 中的 flag

        return SaResult.ok("容器已删除，数据库记录已更新");
    }
    /**
     * 查看容器状态
     *
     * @param containerId 容器ID
     * @return 容器状态
     */
    @GetMapping("/checkStatus/{containerId}")
    public SaResult checkStatus(@PathVariable String containerId) {
        // 获取容器状态
       dockerUtils.inspectContainer(containerId);
       return SaResult.ok("获取容器状态成功");
   }

}

